﻿export class Renderer {
  constructor(ctx, board, services = {}) {
    this.ctx = ctx;
    this.board = board;
    this.services = services;
    this.padding = 20;
    this.cardRects = [];
    this.menuRects = [];
    this.settingsRects = [];
    this.controlRects = []; // 新增：顶部控制按钮
  }

  render() {
    const ctx = this.ctx;
    const state = this.services.state || {};
    ctx.imageSmoothingEnabled = !!(state.settings?.pixelSmooth);
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

    if (state.status === 'menu') { this.drawMainMenu(); return; }
    if (state.status === 'settings') { this.drawSettings(); return; }

    this.drawBoard();
    this.drawCardBar();
    this.drawPlants();
    this.drawProjectiles();
    this.drawZombies();
    this.drawOverlay(state.status);
  }

  drawBoard() {
    const ctx = this.ctx;
    const w = ctx.canvas.width, h = ctx.canvas.height;
    const gridW = w - this.padding * 2; const gridH = h - this.padding * 2 - 40;
    const cellW = gridW / this.board.cols; const cellH = gridH / this.board.rows;
    ctx.fillStyle = '#7fbf7f';
    ctx.fillRect(this.padding, this.padding + 40, gridW, gridH);
    ctx.strokeStyle = '#558b6e';
    for (let r = 0; r < this.board.rows; r++) {
      for (let c = 0; c < this.board.cols; c++) {
        const x = this.padding + c * cellW;
        const y = this.padding + 40 + r * cellH;
        ctx.strokeRect(x, y, cellW, cellH);
      }
    }
  }

  drawCardBar() {
    const ctx = this.ctx;
    const w = ctx.canvas.width;
    const cards = this.services.state?.cards || [];
    const cooldowns = this.services.cooldowns;
    const sun = this.services.sun;
  
    this.cardRects = [];
    this.controlRects = [];
    ctx.fillStyle = '#2e5c39';
    ctx.fillRect(this.padding, this.padding, w - this.padding * 2, 32);
    ctx.fillStyle = '#e6f3e8';
    ctx.font = '14px Segoe UI, Arial';
    ctx.fillText(`阳光: ${sun?.suns ?? 0}`, this.padding + 8, this.padding + 22);
  
    const bw = 90, bh = 28, gap = 8; let x = this.padding + 120; const y = this.padding + 2;
    for (let i = 0; i < cards.length; i++) {
      const card = cards[i];
      // 新增：卡片冷却条—根据剩余冷却和配置时长绘制进度
      const cfg = this.services.configs?.plants?.[card.id] || {};
      const duration = Number(cfg.cooldownMs) || 5000;
      const remaining = cooldowns?.get?.(`card:${card.id}`) ?? 0;
      const inCd = remaining > 0;
      const progress = duration > 0 ? (1 - Math.min(1, remaining / duration)) : 1; // 充能进度（越接近1越可用）

      ctx.fillStyle = inCd ? '#4a6a52' : '#3b5a45';
      ctx.fillRect(x, y, bw, bh);
      ctx.strokeStyle = '#1b3b22'; ctx.strokeRect(x, y, bw, bh);
      ctx.fillStyle = '#e6f3e8'; ctx.font = '12px Segoe UI, Arial';
      ctx.fillText(`${card.name}(${card.cost})`, x + 6, y + 18);
      if (inCd) {
        // 显示剩余秒数
        ctx.fillText(`${Math.ceil(remaining/1000)}s`, x + bw - 26, y + 18);
        // 冷却条（底部细条）：蓝色显示充能进度
        const barPad = 3; const barH = 4; const barW = bw - barPad * 2; const barX = x + barPad; const barY = y + bh - barH - 2;
        ctx.fillStyle = '#333'; ctx.fillRect(barX, barY, barW, barH);
        ctx.fillStyle = '#4a8cff'; ctx.fillRect(barX, barY, Math.max(0, Math.min(barW, barW * progress)), barH);
        ctx.strokeStyle = '#1f2a44'; ctx.strokeRect(barX, barY, barW, barH);
      }
      this.cardRects.push({ x, y, w: bw, h: bh });
      x += bw + gap;
    }
  
    // 右侧控制按钮：暂停/继续、结束
    const ctrlBw = 70, ctrlBh = 28, ctrlGap = 10;
    const totalCtrlW = ctrlBw * 2 + ctrlGap;
    let cx = w - this.padding - totalCtrlW - 8; const cy = this.padding + 2;
    const status = this.services.state?.status;
    const pauseLabel = status === 'paused' ? '继续' : '暂停';
  
    const drawCtrl = (label, id) => {
      ctx.fillStyle = '#3b5a45';
      ctx.fillRect(cx, cy, ctrlBw, ctrlBh);
      ctx.strokeStyle = '#1b3b22'; ctx.strokeRect(cx, cy, ctrlBw, ctrlBh);
      ctx.fillStyle = '#e6f3e8'; ctx.font = '12px Segoe UI, Arial';
      const lw = ctx.measureText(label).width;
      ctx.fillText(label, cx + (ctrlBw - lw) / 2, cy + 18);
      this.controlRects.push({ id, x: cx, y: cy, w: ctrlBw, h: ctrlBh });
      cx += ctrlBw + ctrlGap;
    };
    drawCtrl(pauseLabel, 'pause_toggle');
    drawCtrl('结束', 'end_game');
  }

  drawPlants() {
    const ctx = this.ctx;
    const state = this.services.state;
    const gridW = ctx.canvas.width - this.padding * 2; const gridH = ctx.canvas.height - this.padding * 2 - 40;
    const cellW = gridW / this.board.cols; const cellH = gridH / this.board.rows;
    for (let r = 0; r < this.board.rows; r++) {
      for (let c = 0; c < this.board.cols; c++) {
        const t = this.board.tiles[r][c];
        const plant = t.plant;
        if (!plant) continue;
        const center = this.gridToPixel(r, c);
        const sprite = this.getPlantSprite(plant.kind);
        if (sprite) {
          const pxSize = Math.min(center.cellW, center.cellH) / (sprite.pattern[0].length);
          this.drawPixelSprite(sprite.pattern, sprite.palette, center.x, center.y, pxSize);
        } else {
          // Fallback
          const x = this.padding + c * cellW + cellW * 0.15;
          const y = this.padding + 40 + r * cellH + cellH * 0.15;
          ctx.fillStyle = '#5aa36a';
          ctx.fillRect(x, y, cellW * 0.7, cellH * 0.7);
        }
        if (state.settings?.showHealthBars !== false) {
          const ratio = Math.max(0, Math.min(1, (Number(plant.hp) || 0) / (Number(plant.maxHp) || Number(plant.hp) || 1)));
          this.drawHealthBar(center.x - center.cellW * 0.35, center.y - center.cellH * 0.45, center.cellW * 0.7, 4, ratio);
        }
        // 新增：根据植物配置显示冷却条（攻击或产阳光）
        const cfg = this.services.configs?.plants?.[plant.kind] || null;
        let cdRatio = null;
        if (cfg?.projectile && cfg?.attackRateMs) {
          const t = plant._t || 0; const rate = cfg.attackRateMs;
          cdRatio = Math.max(0, Math.min(1, t / rate));
        } else if (cfg?.produceSun && cfg?.produceRateMs) {
          const t = plant._sunT || 0; const rate = cfg.produceRateMs;
          cdRatio = Math.max(0, Math.min(1, t / rate));
        }
        if (cdRatio !== null) {
          this.drawCooldownBar(center.x - center.cellW * 0.35, center.y - center.cellH * 0.35, center.cellW * 0.7, 4, cdRatio);
        }
      }
    }
  }

  drawProjectiles() {
    const ctx = this.ctx;
    const ps = this.services.state?.projectiles || [];
    ctx.fillStyle = '#e6f3e8';
    for (const p of ps) {
      ctx.beginPath();
      ctx.arc(p.x, p.y, 4, 0, Math.PI * 2);
      ctx.fill();
    }
  }

  drawZombies() {
    const ctx = this.ctx;
    const zs = this.services.state?.zombies || [];
    const w = ctx.canvas.width, h = ctx.canvas.height;
    const gridW = w - this.padding * 2; const gridH = h - this.padding * 2 - 40;
    const cellW = gridW / this.board.cols; const cellH = gridH / this.board.rows;
    for (const z of zs) {
      const center = { x: z.x, y: z.y, cellW, cellH };
      const sprite = this.getZombieSprite(z.type);
      if (sprite) {
        const pxSize = Math.min(cellW, cellH) / (sprite.pattern[0].length);
        this.drawPixelSprite(sprite.pattern, sprite.palette, center.x, center.y, pxSize);
      } else {
        // Fallback
        const x = z.x - cellW * 0.3; const y = z.y - cellH * 0.3;
        ctx.fillStyle = '#6f757a';
        ctx.fillRect(x, y, cellW * 0.6, cellH * 0.6);
      }
      if (this.services.state?.settings?.showHealthBars !== false) {
        const hp = Number(z.hp) || 0;
        const maxHp = Number(z.maxHp) || Number(this.services.configs?.zombies?.[z.type]?.hp) || 200;
        const ratio = Math.max(0, Math.min(1, hp / maxHp));
        this.drawHealthBar(center.x - cellW * 0.3, center.y - cellH * 0.45, cellW * 0.6, 4, ratio);
      }
    }
  }

  drawOverlay(status) {
    const ctx = this.ctx;
    if (status !== 'won' && status !== 'lost' && status !== 'paused') return;
    ctx.fillStyle = 'rgba(0,0,0,0.35)';
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.fillStyle = '#e6f3e8'; ctx.font = 'bold 28px Segoe UI, Arial';
    let text = '暂停中';
    if (status === 'won') text = '胜利！';
    if (status === 'lost') text = '失败！';
    const tw = ctx.measureText(text).width;
    ctx.fillText(text, (ctx.canvas.width - tw) / 2, ctx.canvas.height * 0.5);
  }

  drawHealthBar(x, y, w, h, ratio) {
    const ctx = this.ctx;
    ctx.fillStyle = '#333'; ctx.fillRect(x, y, w, h);
    ctx.fillStyle = '#ff5a5a'; ctx.fillRect(x, y, w * ratio, h);
    ctx.strokeStyle = '#222'; ctx.strokeRect(x, y, w, h);
  }

  // 新增：植物冷却条绘制（攻击或产阳光充能进度）
  drawCooldownBar(x, y, w, h, ratio) {
    const ctx = this.ctx;
    ctx.fillStyle = '#333'; ctx.fillRect(x, y, w, h);
    ctx.fillStyle = '#4a8cff'; ctx.fillRect(x, y, w * ratio, h);
    ctx.strokeStyle = '#1f2a44'; ctx.strokeRect(x, y, w, h);
  }

  // 像素精灵渲染
  drawPixelSprite(pattern, palette, cx, cy, size) {
    const rows = pattern.length;
    const cols = pattern[0]?.length || 0;
    const startX = cx - (cols * size) / 2;
    const startY = cy - (rows * size) / 2;
    const ctx = this.ctx;
    for (let r = 0; r < rows; r++) {
      const line = pattern[r];
      for (let c = 0; c < cols; c++) {
        const ch = line[c];
        if (!ch || ch === '.') continue;
        const color = palette[ch];
        if (!color) continue;
        ctx.fillStyle = color;
        ctx.fillRect(startX + c * size, startY + r * size, size, size);
      }
    }
  }

  getPlantSprite(kind) {
    switch (kind) {
      case 'peashooter': return {
        pattern: [
          "..LLGGGGLL..",
          ".LGGGYYGGGGL",
          ".LGGGYYGGGGL",
          "..LGGGGGGL..",
          "...SSSSS....",
          "..LG.LL.LG..",
          "...L....L..."
        ],
        palette: {
          'G':'#5aa36a', // 叶片中绿
          'L':'#4e8d5e', // 叶片深绿轮廓
          'S':'#3b5a45', // 茎杆
          'Y':'#e6f3e8'  // 头部高光
        }
      };
      case 'snowpea': return {
        pattern: [
          "..LLGGGGLL..",
          ".LGGGIIGGGGL",
          ".LGGIYYIGGGL",
          "..LGGIIGGGL.",
          "...SSSSS....",
          "..LG.LL.LG..",
          "...L....L..."
        ],
        palette: {
          'G':'#5aa36a',
          'L':'#4e8d5e',
          'S':'#3b5a45',
          'I':'#9bd1ff', // 冰蓝
          'Y':'#e6f3e8'  // 高光
        }
      };
      case 'repeater': return {
        pattern: [
          "..LLGG..GGLL",
          ".LGGGYYGGGGL",
          ".LGGGYYGGGGL",
          "..LGGGGGGGL.",
          "...SSSSSS...",
          "..LG.LL.LG..",
          "...L....L..."
        ],
        palette: {
          'G':'#5aa36a',
          'L':'#4e8d5e',
          'S':'#3b5a45',
          'Y':'#e6f3e8'
        }
      };
      case 'sunflower': return {
        pattern: [
          "..PYYYYYYP..",
          ".PYYOOOOYYP.",
          ".YYOOooOOYY.",
          ".YYOOooOOYY.",
          ".PYYOOOOYYP.",
          "..PYYYYYYP..",
          "...LG..GL...",
          "...LLLLLL..."
        ],
        palette: {
          'Y':'#f7d84a', // 花瓣主色
          'P':'#eecb3a', // 花瓣阴影/高光变化
          'O':'#8b5a2b', // 花盘深色
          'o':'#a66a3c', // 花盘浅色
          'L':'#4e8d5e', // 叶片深绿
          'G':'#5aa36a'  // 叶片中绿
        }
      };
      case 'wallnut': return {
        pattern: [
          "...OOOOOOOO..",
          "..OOOooooOO..",
          "..OOooooOOO..",
          "..OOOooooOO..",
          "...OOOOOOOO..",
          "...LG..GL....",
          "...LLLLLL...."
        ],
        palette: {
          'O':'#8b5a2b', // 坚果壳深色
          'o':'#a66a3c', // 壳浅色
          'L':'#4e8d5e',
          'G':'#5aa36a'
        }
      };
      default:
        return null;
    }
  }

  getZombieSprite(type) {
    switch (type) {
      case 'basic': return {
        pattern: [
          '....HHHH....',
          '...HZZZZH...',
          '..HZZRZZZH..',
          '..HZZZZZZH..',
          '...HZZZZH...',
          '....TTTT....',
          '....TTTT....',
          '....TTTT....',
          '...LLLLLL...',
          '..LL....LL..',
          '..LL....LL..'
        ],
        palette: { 'H':'#9aa0a6', 'Z':'#6f757a', 'R':'#ff5a5a', 'T':'#8b5a2b', 'L':'#55606a' }
      };
      case 'cone': return {
        pattern: [
          '....CCCC....',
          '...CHHHHC...',
          '..HZZZZZZH..',
          '..HZZRZZZH..',
          '..HZZZZZZH..',
          '...HZZZZH...',
          '....TTTT....',
          '....TTTT....',
          '....TTTT....',
          '...LLLLLL...',
          '..LL....LL..',
          '..LL....LL..'
        ],
        palette: { 'C':'#f07f3e', 'H':'#9aa0a6', 'Z':'#6f757a', 'R':'#ff5a5a', 'T':'#8b5a2b', 'L':'#55606a' }
      };
      case 'bucket': return {
        pattern: [
          '...KKKKKK...',
          '...KHHHHK...',
          '..HZZZZZZH..',
          '..HZZRZZZH..',
          '..HZZZZZZH..',
          '...HZZZZH...',
          '....TTTT....',
          '....TTTT....',
          '....TTTT....',
          '...LLLLLL...',
          '..LL....LL..',
          '..LL....LL..'
        ],
        palette: { 'K':'#b8b8b8', 'H':'#9aa0a6', 'Z':'#6f757a', 'R':'#ff5a5a', 'T':'#8b5a2b', 'L':'#55606a' }
      };
      default: return null;
    }
  }

  pickGrid(px, py) {
    const w = this.ctx.canvas.width, h = this.ctx.canvas.height;
    const gridW = w - this.padding * 2; const gridH = h - this.padding * 2 - 40;
    const cellW = gridW / this.board.cols; const cellH = gridH / this.board.rows;
    const x = px - this.padding; const y = py - (this.padding + 40);
    const col = Math.floor(x / cellW); const row = Math.floor(y / cellH);
    return { row: Math.max(0, Math.min(this.board.rows - 1, row)), col: Math.max(0, Math.min(this.board.cols - 1, col)) };
  }

  pickCard(px, py) {
    for (let i = 0; i < this.cardRects.length; i++) {
      const r = this.cardRects[i];
      if (px >= r.x && px <= r.x + r.w && py >= r.y && py <= r.y + r.h) return i;
    }
    return -1;
  }

  gridToPixel(row, col) {
    const w = this.ctx.canvas.width, h = this.ctx.canvas.height;
    const gridW = w - this.padding * 2; const gridH = h - this.padding * 2 - 40;
    const cellW = gridW / this.board.cols; const cellH = gridH / this.board.rows;
    const x = this.padding + col * cellW + cellW * 0.5;
    const y = this.padding + 40 + row * cellH + cellH * 0.5;
    return { x, y, cellW, cellH, gridW, gridH };
  }

  drawMainMenu() {
    const ctx = this.ctx;
    const w = ctx.canvas.width, h = ctx.canvas.height;
    this.menuRects = [];
    ctx.fillStyle = '#2e5c39'; ctx.fillRect(0, 0, w, h);
    ctx.fillStyle = '#e6f3e8'; ctx.font = 'bold 36px Segoe UI, Arial';
    const title = '植物大战僵尸 — 主菜单';
    const tw = ctx.measureText(title).width;
    ctx.fillText(title, (w - tw) / 2, h * 0.28);
    const bw = 220, bh = 50; const gap = 18; const bx = (w - bw) / 2; let by = h * 0.42;
    const drawBtn = (label, id) => {
      ctx.fillStyle = '#244a30'; ctx.fillRect(bx, by, bw, bh);
      ctx.strokeStyle = '#1b3b22'; ctx.lineWidth = 2; ctx.strokeRect(bx, by, bw, bh);
      ctx.fillStyle = '#e6f3e8'; ctx.font = 'bold 20px Segoe UI, Arial';
      const lw = ctx.measureText(label).width;
      ctx.fillText(label, bx + (bw - lw) / 2, by + bh / 2 + 7);
      this.menuRects.push({ id, x: bx, y: by, w: bw, h: bh });
      by += bh + gap;
    };
    drawBtn('开始游戏', 'start');
    drawBtn('设置', 'settings');
  }

  drawSettings() {
    const ctx = this.ctx;
    const w = ctx.canvas.width, h = ctx.canvas.height;
    this.settingsRects = [];
    ctx.fillStyle = 'rgba(0,0,0,0.55)'; ctx.fillRect(0, 0, w, h);
    const pw = 520, ph = 320; const px = (w - pw) / 2; const py = (h - ph) / 2;
    ctx.fillStyle = '#244a30'; ctx.fillRect(px, py, pw, ph);
    ctx.strokeStyle = '#1b3b22'; ctx.lineWidth = 2; ctx.strokeRect(px, py, pw, ph);
    ctx.fillStyle = '#e6f3e8'; ctx.font = 'bold 24px Segoe UI, Arial';
    ctx.fillText('设置', px + 20, py + 40);

    const s = this.services.state?.settings || {};
    ctx.font = '16px Segoe UI, Arial';
    const optY0 = py + 90;
    const label1 = `显示血条: ${s.showHealthBars !== false ? '开' : '关'}`;
    ctx.fillText(label1, px + 24, optY0);
    const b1 = { x: px + pw - 160, y: optY0 - 24, w: 120, h: 32 };
    ctx.fillStyle = '#2e5c39'; ctx.fillRect(b1.x, b1.y, b1.w, b1.h);
    ctx.strokeStyle = '#1b3b22'; ctx.strokeRect(b1.x, b1.y, b1.w, b1.h);
    ctx.fillStyle = '#e6f3e8'; ctx.fillText('切换', b1.x + 40, b1.y + 22);
    this.settingsRects.push({ id: 'toggle_health', ...b1 });

    const label2 = `像素平滑: ${s.pixelSmooth ? '开' : '关'}`;
    ctx.fillStyle = '#e6f3e8'; ctx.fillText(label2, px + 24, optY0 + 50);
    const b2 = { x: px + pw - 160, y: optY0 + 26, w: 120, h: 32 };
    ctx.fillStyle = '#2e5c39'; ctx.fillRect(b2.x, b2.y, b2.w, b2.h);
    ctx.strokeStyle = '#1b3b22'; ctx.strokeRect(b2.x, b2.y, b2.w, b2.h);
    ctx.fillStyle = '#e6f3e8'; ctx.fillText('切换', b2.x + 40, b2.y + 22);
    this.settingsRects.push({ id: 'toggle_smooth', ...b2 });

    const bw = 180, bh = 42; const bx = px + (pw - bw) / 2; const by = py + ph - bh - 20;
    ctx.fillStyle = '#2e5c39'; ctx.fillRect(bx, by, bw, bh);
    ctx.strokeStyle = '#1b3b22'; ctx.strokeRect(bx, by, bw, bh);
    ctx.fillStyle = '#e6f3e8'; ctx.font = 'bold 18px Segoe UI, Arial';
    const lw = ctx.measureText('返回主菜单').width; ctx.fillText('返回主菜单', bx + (bw - lw) / 2, by + bh / 2 + 7);
    this.settingsRects.push({ id: 'back', x: bx, y: by, w: bw, h: bh });
  }

  pickMenu(px, py) {
    for (const r of this.menuRects) { if (px >= r.x && px <= r.x + r.w && py >= r.y && py <= r.y + r.h) return r.id; }
    return null;
  }
  pickSettings(px, py) {
    for (const r of this.settingsRects) { if (px >= r.x && px <= r.x + r.w && py >= r.y && py <= r.y + r.h) return r.id; }
    return null;
  }
  // 新增：选择顶部控制按钮
  pickControls(px, py) {
    for (const r of this.controlRects) { if (px >= r.x && px <= r.x + r.w && py >= r.y && py <= r.y + r.h) return r.id; }
    return null;
  }
}